package com.zhangxin.aiInterview.controller;

import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.zhangxin.aiInterview.annotation.AuthCheck;
import com.zhangxin.aiInterview.common.BaseResponse;
import com.zhangxin.aiInterview.common.ErrorCode;
import com.zhangxin.aiInterview.common.ResultUtils;
import com.zhangxin.aiInterview.constant.UserConstant;
import com.zhangxin.aiInterview.exception.BusinessException;
import com.zhangxin.aiInterview.manager.knoewlege_base_api.dto.ExamQuestionWrapper;
import com.zhangxin.aiInterview.manager.redis.rate_limiter.RateLimitManager;
import com.zhangxin.aiInterview.model.dto.exam.DebugCodeRequest;
import com.zhangxin.aiInterview.model.dto.exam.ExamGenerateRequest;
import com.zhangxin.aiInterview.model.dto.exam.ExamGetResultRequest;
import com.zhangxin.aiInterview.model.entity.Exam;
import com.zhangxin.aiInterview.model.entity.ExamAnalysisResult;
import com.zhangxin.aiInterview.model.enums.AnalyzeStatusEnum;
import com.zhangxin.aiInterview.model.enums.IsFullInterviewEnum;
import com.zhangxin.aiInterview.model.vo.WrongProgramingInfoVO;
import com.zhangxin.aiInterview.model.vo.response.DebugCodeResponse;
import com.zhangxin.aiInterview.model.vo.response.GetExamAnalyzeResultResponse;
import com.zhangxin.aiInterview.model.vo.response.PartQuestionCountResponse;
import com.zhangxin.aiInterview.service.ExamAnalysisResultService;
import com.zhangxin.aiInterview.service.ExamContentService;
import com.zhangxin.aiInterview.service.ExamService;
import com.zhangxin.aiInterview.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.List;

/**
 * 笔试接口
 */
@RestController
@RequestMapping("/exam")
@Slf4j
public class ExamController {
    @Resource
    private ExamService examService;
    @Resource
    private UserService userService;
    @Resource
    private ExamAnalysisResultService examAnalysisResultService;
    @Resource
    private RateLimitManager rateLimitManager;

    /**
     * 批量查询用户笔试记录
     *
     * @param request
     * @return
     */
    @GetMapping("/get/user/exam")
    @AuthCheck(mustRole = UserConstant.DEFAULT_ROLE)
    public BaseResponse<List<Exam>> getExamList(HttpServletRequest request) {
        Long userId = userService.getLoginUser(request).getId();
        List<Exam> examList = examService.lambdaQuery()
                .eq(Exam::getUserId, userId)
                .eq(Exam::getIsFull, IsFullInterviewEnum.IS_NOT_FULL_INTERVIEW.getValue())
                .orderByDesc(Exam::getCreateTime)
                .list();
        return ResultUtils.success(examList);
    }

    /**
     * 生成笔试题目
     *
     * @param examGenerateRequest
     * @param request
     * @return
     */
    @PostMapping("/generate")
    @AuthCheck(mustRole = UserConstant.DEFAULT_ROLE)
    public BaseResponse<Long> generateExam(@RequestBody ExamGenerateRequest examGenerateRequest, HttpServletRequest request) {
        Long techFieldId = examGenerateRequest.getTechFieldId();
        Long positionId = examGenerateRequest.getPositionId();
        Long companyId = examGenerateRequest.getCompanyId();
        if (ObjUtil.isEmpty(techFieldId) || ObjUtil.isEmpty(positionId)) {
            throw new BusinessException(ErrorCode.OPERATION_ERROR, "面试公司和笔试岗位不能为空");
        }
        //生成笔试题目
        Long examId = examService.generateExam(techFieldId, positionId, companyId, request, false, null);
        return ResultUtils.success(examId);
    }

    /**
     * 根据笔试id查询题目
     *
     * @param examId
     * @param request
     * @return
     */
    @GetMapping("/get/question")
    @AuthCheck(mustRole = UserConstant.DEFAULT_ROLE)
    public BaseResponse<ExamQuestionWrapper> getQuestion(@RequestParam("examId") Long examId, HttpServletRequest request) {
        ExamQuestionWrapper question = examService.getQuestion(examId, request);
        return ResultUtils.success(question);
    }

    /**
     * 取消笔试
     * @param examId
     * @return
     */
    @PostMapping("/cancel")
    public BaseResponse<Boolean> cancelExam(@RequestParam(value = "examId") Long examId) {
        boolean update = examService.lambdaUpdate()
                .eq(Exam::getId, examId)
                .set(Exam::getExamStatus, AnalyzeStatusEnum.UNFINISHED.getValue())
                .update();
        return ResultUtils.success(update);
    }

    /**
     * 分析笔试结果
     *
     * @param examGetResultRequest
     */
    @PostMapping("/analyze/examResult")
    @AuthCheck(mustRole = UserConstant.DEFAULT_ROLE)
    public boolean analyzeExamResult(@RequestBody ExamGetResultRequest examGetResultRequest, HttpServletRequest request) {
        Long userId = userService.getLoginUser(request).getId();
        Long examId = examGetResultRequest.getExamId();
        Integer examDuration = examGetResultRequest.getExamDuration();
        String answers = examGetResultRequest.getAnswers();
        Boolean isFull = examGetResultRequest.getIsFull();
        Long fullInterviewId = examGetResultRequest.getFullInterviewId();

        return examService.analyzeExamResult(userId, examId, examDuration, answers, isFull, fullInterviewId);
    }

    /**
     * 获取笔试分析结果
     *
     * @param examId
     * @return
     */
    @GetMapping("/get/analyze/result")
    @AuthCheck(mustRole = UserConstant.DEFAULT_ROLE)
    public BaseResponse<GetExamAnalyzeResultResponse> getExamAnalyzeResult(@RequestParam("examId") Long examId) {

        GetExamAnalyzeResultResponse getExamAnalyzeResultResponse = examService.getExamAnalyzeResult(examId);
        return ResultUtils.success(getExamAnalyzeResultResponse);
    }

    /**
     * 获取错误编程题信息
     * @param examId
     * @return
     */
    @GetMapping("/get/wrongProgramingInfo")
    public BaseResponse<List<List<WrongProgramingInfoVO>>> getWrongProgramingInfo(@RequestParam("examId") Long examId) {

        //列表中的元素是每一条查询到的数据
        ExamAnalysisResult examAnalysisResult = examAnalysisResultService.lambdaQuery()
                .eq(ExamAnalysisResult::getExamId, examId)
                .select(ExamAnalysisResult::getWrongProgramingUrl)
                .one();
        if(ObjUtil.isEmpty(examAnalysisResult)) return ResultUtils.success(new ArrayList<>());
        String jsonStr = examAnalysisResult.getWrongProgramingUrl();

        // 使用 Hutool 解析
        JSONArray outerArray = JSONUtil.parseArray(jsonStr);

        List<List<WrongProgramingInfoVO>> result = new ArrayList<>();

        for (Object inner : outerArray) {
            JSONArray innerArray = (JSONArray) inner;
            List<WrongProgramingInfoVO> innerList = new ArrayList<>();

            for (Object item : innerArray) {
                cn.hutool.json.JSONObject jsonObject = (JSONObject) item;
                WrongProgramingInfoVO vo = new WrongProgramingInfoVO();
                vo.setName(jsonObject.getStr("name"));
                vo.setUrl(jsonObject.getStr("url"));
                innerList.add(vo);
            }
            result.add(innerList);
        }
        return ResultUtils.success(result);
    }

    /**
     * 测试代码
     *
     * @param debugCodeRequest
     * @return
     */
    @PostMapping("/debug/code")
    @AuthCheck(mustRole = UserConstant.DEFAULT_ROLE)
    public BaseResponse<DebugCodeResponse> debugCode(@RequestBody DebugCodeRequest debugCodeRequest) {
        String code = debugCodeRequest.getCode();
        if (StrUtil.isBlank(code)) throw new BusinessException(ErrorCode.OPERATION_ERROR, "请编写代码后再进行调试");
        DebugCodeResponse debugCodeResponse = examService.debugCode(JSONUtil.toJsonStr(debugCodeRequest));
        return ResultUtils.success(debugCodeResponse);
    }

    /**
     * 获取各部分问题数量
     *
     * @param examId
     * @return
     */
    @GetMapping("/get/partQuestion/count")
    @AuthCheck(mustRole = UserConstant.DEFAULT_ROLE)
    public BaseResponse<PartQuestionCountResponse> getPartQuestionCount(Long examId) {
        PartQuestionCountResponse count = examService.getPartQuestionCount(examId);
        return ResultUtils.success(count);
    }

    /**
     * 删除笔试记录
     * @param examId
     * @param request
     * @return
     */
    @GetMapping("/delete")
    @AuthCheck(mustRole = UserConstant.DEFAULT_ROLE)
    public BaseResponse<Boolean> deleteExam(@RequestParam(value = "examId") Long examId,HttpServletRequest request) {
        boolean b = examService.deleteExam(examId,request);
        return ResultUtils.success(b);
    }

    /**
     * 公共接口：生成笔试题
     * 提供给外部系统直接调用，无需权限校验
     * 根据公司、岗位、面试角色生成对应的笔试题目
     *
     * @param company 公司名称
     * @param position 岗位名称
     * @param interviewRole 面试角色（如：实习、校招、社招）
     * @return 生成的笔试题内容
     */
    @PostMapping("/public/generate")
    public BaseResponse<String> publicGenerateExam(
            @RequestParam("company") String company,
            @RequestParam("position") String position,
            @RequestParam("interviewRole") String interviewRole,
            HttpServletRequest request) {
        
        try {
            // 获取客户端IP
            String clientIp = rateLimitManager.getClientIpAddress(request);
            String rateLimitKey = "AI_interview:public:rateLimiting:examGenerate:" + clientIp;
            
            // 检查限流（1分钟1次）
            if (!rateLimitManager.isAllowed(rateLimitKey, 1, 60)) {
                log.warn("笔试生成接口触发限流：IP={}", clientIp);
                throw new BusinessException(ErrorCode.OPERATION_ERROR, "请求过于频繁，请稍后再试");
            }
            
            log.info("公共接口收到笔试题生成请求：公司={}, 岗位={}, 面试角色={}, IP={}", company, position, interviewRole, clientIp);
            
            // 参数校验
            if (StrUtil.isBlank(company)) {
                throw new BusinessException(ErrorCode.PARAMS_ERROR, "公司名称不能为空");
            }
            if (StrUtil.isBlank(position)) {
                throw new BusinessException(ErrorCode.PARAMS_ERROR, "岗位名称不能为空");
            }
            if (StrUtil.isBlank(interviewRole)) {
                throw new BusinessException(ErrorCode.PARAMS_ERROR, "面试角色不能为空");
            }
            
            // 调用笔试题生成服务
            String examQuestions = examService.publicGenerateExam(company, position, interviewRole);
            
            return ResultUtils.success(examQuestions);
            
        } catch (BusinessException e) {
            log.error("公共接口笔试题生成业务异常", e);
            throw e;
        } catch (Exception e) {
            log.error("公共接口笔试题生成系统异常", e);
            throw new BusinessException(ErrorCode.SYSTEM_ERROR, "笔试题生成失败：" + e.getMessage());
        }
    }
}